package cn.flying.cloud.task.core.quartz.scheduler;

import javax.annotation.Resource;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import cn.flying.cloud.base.common.utils.Ft;
import cn.flying.cloud.task.core.quartz.constants.TaskConstant;
import cn.flying.cloud.task.core.quartz.exception.TaskException;
import cn.flying.cloud.task.core.quartz.job.ScheduleJobExecution;
import cn.flying.cloud.task.entity.TaskJobInfo;

/**
 * 任务调度管理
 *
 * @author: admin
 * @date: 2024年01月29日 10:40
 * @version: 1.0
 */
@Component
public class ScheduleManager implements ApplicationContextAware {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private ApplicationContext applicationContext;

    @Resource
    private Scheduler scheduler;

    /**
     *
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * 获取调度器
     *
     * @return
     */
    public Scheduler scheduler() {
        return scheduler;
    }

    /**
     * 创建一个Cron表达式触发器
     *
     * @param jobName  任务名称
     * @param jobGroup 任务所属分组
     * @param jobCron  cron表达式
     * @return
     */
    public CronTrigger newCronTrigger(String jobName, String jobGroup, String jobCron) {
        // 表达式调度构建器(即任务执行的时间)
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(jobCron);

        // 按新的cronExpression表达式构建一个新的trigger
        return TriggerBuilder.newTrigger()
                .withIdentity(TriggerKey.triggerKey(jobName, jobGroup))
                .withSchedule(scheduleBuilder)
                .build();
    }

    /**
     * 启动定时任务，加入调度
     *
     * @param jobInfo
     */
    public void startJob(TaskJobInfo jobInfo) {
        try {
//            String jobTarget = jobInfo.getJobTarget();
//            Object bean = applicationContext.getBean(jobTarget);
//            Class<? extends Job> clazz = (Class<? extends Job>) bean.getClass();

            // 构建job信息
            JobDetail jobDetail = JobBuilder.newJob(ScheduleJobExecution.class)
                    .withIdentity(JobKey.jobKey(jobInfo.getJobName(), jobInfo.getJobGroup()))
                    .withDescription(jobInfo.getJobDesc())
                    .build();

            // 表达式调度构建器
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(jobInfo.getJobCron())
                    .withMisfireHandlingInstructionDoNothing();

            // 按新的cronExpression表达式构建一个新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(TriggerKey.triggerKey(jobInfo.getJobName(), jobInfo.getJobGroup()))
                    .withSchedule(cronScheduleBuilder)
                    .build();

            // 放入任务对象信息，运行时的方法可以获取
            jobDetail.getJobDataMap().put(TaskConstant.JOB_PERSISTENCE, jobInfo);

            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            logger.error("启动定时任务异常：", e);
            throw new TaskException("启动定时任务异常！", e);
        }
    }

    /**
     * 停止、删除任务（表示完全不用了，下线了，如需重新启用，需要重新使用调度：）
     *
     * @param jobName  任务名称
     * @param jobGroup 任务所属分组
     */
    public void stopJob(String jobName, String jobGroup) {
        try {
            // 暂停触发器
            scheduler.pauseTrigger(TriggerKey.triggerKey(jobName, jobGroup));
            // 移除触发器
            scheduler.unscheduleJob(TriggerKey.triggerKey(jobName, jobGroup));
            // 删除任务
            scheduler.deleteJob(JobKey.jobKey(jobName, jobGroup));
        } catch (SchedulerException e) {
            logger.error("停止任务异常：", e);
            throw new TaskException("停止任务异常！", e);
        }
    }

//    /**
//     * 更新定时任务
//     *
//     * @param jobInfo
//     */
//    public void updateScheduleJob(TaskJobInfo jobInfo) {
//        try {
//            TriggerKey triggerKey = TriggerKey.triggerKey(jobInfo.getJobName(), jobInfo.getJobGroup());
//
//            // 表达式调度构建器
//            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(jobInfo.getJobCron())
//                    .withMisfireHandlingInstructionDoNothing();
//
//            CronTrigger trigger = getCronTrigger(jobInfo.getJobName(), jobInfo.getJobGroup());
//
//            // 按新的cronExpression表达式重新构建trigger
//            trigger = trigger.getTriggerBuilder()
//                    .withIdentity(triggerKey)
//                    .withSchedule(cronScheduleBuilder)
//                    .build();
//
//            // 放入任务对象信息，运行时的方法可以获取
//            trigger.getJobDataMap().put(TaskConstant.JOB_PERSISTENCE, jobInfo);
//
//            // 调度任务，系统默认会自动运行
//            scheduler.rescheduleJob(triggerKey, trigger);
//
//            // 没有设置运行，暂停任务
//            if (!JobStatusEnum.RUNNING.getCode().equals(jobInfo.getStatus())) {
//                pauseJob(jobInfo.getJobName(), jobInfo.getJobGroup());
//            }
//
//        } catch (SchedulerException e) {
//            logger.error("更新定时任务异常：", e);
//            throw new TaskException("更新定时任务异常！", e);
//        }
//    }

    /**
     * 根据任务名称获取Cron表达式触发器
     *
     * @param jobName  任务名称
     * @param jobGroup 任务所属分组
     * @return
     */
    private CronTrigger getCronTrigger(String jobName, String jobGroup) throws SchedulerException {
        return (CronTrigger) scheduler.getTrigger(TriggerKey.triggerKey(jobName, jobGroup));
    }

    /**
     * 立即触发执行一次任务
     *
     * @param jobName  任务名称
     * @param jobGroup 任务所属分组
     * @return
     */
    public void triggerJob(String jobName, String jobGroup, String param) {
        try {
            if (Ft.String.isNotBlank(param)) {
                Ft.LocalCache.set(jobGroup + ":" + jobName + ":" + "jobParam", param);
            }
            scheduler.triggerJob(JobKey.jobKey(jobName, jobGroup));
        } catch (SchedulerException e) {
            logger.error("触发定时任务异常！", e);
            throw new TaskException("触发定时任务异常！", e);
        }
    }

    /**
     * 暂停任务
     *
     * @param jobName  任务名称
     * @param jobGroup 任务所属分组
     */
    public void pauseJob(String jobName, String jobGroup) {
        try {
            scheduler.pauseJob(JobKey.jobKey(jobName, jobGroup));
        } catch (SchedulerException e) {
            logger.error("暂停任务异常：", e);
            throw new TaskException("暂停任务异常！", e);
        }
    }

    /**
     * 暂停所有任务
     *
     * @param
     */
    public void pauseAllJob() {
        try {
            scheduler.pauseAll();
        } catch (SchedulerException e) {
            logger.error("暂停任务异常：", e);
            throw new TaskException("暂停任务异常！", e);
        }
    }

    /**
     * 恢复任务
     *
     * @param jobName  任务名称
     * @param jobGroup 任务所属分组
     */
    public void resumeJob(String jobName, String jobGroup) {
        try {
            scheduler.resumeJob(JobKey.jobKey(jobName, jobGroup));
        } catch (SchedulerException e) {
            logger.error("恢复任务异常：", e);
            throw new TaskException("恢复任务异常！", e);
        }
    }

    /**
     * 恢复所有任务
     *
     * @param scheduler
     */
    public void resumeAllJob(Scheduler scheduler) {
        try {
            scheduler.resumeAll();
        } catch (SchedulerException e) {
            logger.error("恢复任务异常：", e);
            throw new TaskException("恢复任务异常！", e);
        }
    }


    /**
     * 清除所有的任务
     */
    public void clearAll() {
        try {
            scheduler.clear();
        } catch (SchedulerException e) {
            throw new TaskException("清空任务异常！", e);
        }
    }
}
